package com.components.headerrecycler

import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager

/**
 * @Author LuoKun
 * @Des
 */
class HeaderViewAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder> {

    /**被包装的Adapter*/
    private var mAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>? = null

    /**存放HeaderView*/
    private var mHeaderViewInfos = mutableListOf<FixedViewInfo>()

    /**存放FooterView*/
    private var mFooterViewInfos = mutableListOf<FixedViewInfo>()

    constructor(mAdapter: RecyclerView.Adapter<RecyclerView.ViewHolder>?) : super() {
        this.mAdapter = mAdapter
        //注册mAdapter的数据变化监听
        mAdapter?.registerAdapterDataObserver(mObserver)
    }

    /**重新设置HeaderView*/
    fun setHeaderViewInfos() {
        if (mHeaderViewInfos.size > 0) {
            mHeaderViewInfos.clear()
            notifyDataSetChanged()
        }
    }

    /**用于监听被包装的Adapter的数据变化的监听器。它将被包装的Adapter的数据变化映射成HeaderViewAdapter的变化*/
    private val mObserver: RecyclerView.AdapterDataObserver = object :
        RecyclerView.AdapterDataObserver() {
        override fun onChanged() {
            notifyDataSetChanged()
        }

        override fun onItemRangeChanged(positionStart: Int, itemCount: Int) {
            super.onItemRangeChanged(positionStart, itemCount)
        }

        override fun onItemRangeChanged(positionStart: Int, itemCount: Int, payload: Any?) {
            notifyItemRangeChanged(getHeadersCount() + positionStart, itemCount, payload)
        }

        override fun onItemRangeInserted(positionStart: Int, itemCount: Int) {
            notifyItemRangeChanged(getHeadersCount() + positionStart, itemCount)
        }

        override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
            notifyItemRangeRemoved(getHeadersCount() + positionStart, itemCount)
        }

        override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) {
            notifyItemMoved(getHeadersCount() + fromPosition, getHeadersCount() + toPosition)
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        /**根据viewType查找对应的HeaderView 或 FooterView。如果没有找到则表示该viewType是普通的列表项*/
        val view: View? = findViewForInfo(viewType)
        return if (view != null) {
            ViewHolder(view)
        } else {
            /**交由mAdapter处理*/
            mAdapter!!.onCreateViewHolder(parent, viewType)
        }
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        /**
         * 如果是HeaderView 或者是 FooterView则不绑定数据。
         * 因为HeaderView和FooterView是由外部传进来的，它们不由列表去更新。
         * */
        if (isHeader(position) || isFooter(position)) {
            return
        }

        /**将列表实际的position调整成mAdapter对应的position*/
        /**交由mAdapter处理*/
        val adjPosition: Int = position - getHeadersCount()
        mAdapter?.onBindViewHolder(holder, adjPosition)
    }

    /**增加三参方法，保证局部刷新的时候不闪烁当前刷新Item*/
    override fun onBindViewHolder(
        holder: RecyclerView.ViewHolder,
        position: Int,
        payloads: MutableList<Any>
    ) {
        if (payloads.isEmpty()) {
            onBindViewHolder(holder, position)
        } else {
            //这里的逻辑和两参的逻辑一样 只是需要在onBindViewHolder时调用三参的方法
            if (isHeader(position) || isFooter(position)) {
                return
            }
            val adjPosition: Int = position - getHeadersCount()
            mAdapter?.onBindViewHolder(holder, adjPosition, payloads)
        }
    }

    override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
        if (holder is ViewHolder) {
            super.onViewAttachedToWindow(holder)
        } else {
            mAdapter?.onViewAttachedToWindow(holder)
        }
        //处理StaggeredGridLayout，保证HeaderView和FooterView占满一行
        if (isStaggeredGridLayout(holder)) {
            handleLayoutIfStaggeredGridLayout(holder, holder.layoutPosition)
        }
    }

    override fun getItemCount(): Int {
        return mHeaderViewInfos.size + mFooterViewInfos.size + (mAdapter?.itemCount ?: 0)
    }

    override fun getItemViewType(position: Int): Int {
        //如果当前item是HeaderView，则返回HeaderView对应的itemViewType
        if (isHeader(position)) {
            return mHeaderViewInfos[position].itemViewType
        }
        //如果当前item是HeaderView，则返回HeaderView对应的itemViewType
        if (isFooter(position)) {
            return mFooterViewInfos[position - mHeaderViewInfos.size - mAdapter!!.itemCount].itemViewType
        }
        /**将列表实际的position调整成mAdapter对应的position*/
        //交由mAdapter处理
        val adjPosition: Int = position - getHeadersCount()
        return mAdapter!!.getItemViewType(adjPosition)
    }

    override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
        if (holder is ViewHolder) {
            super.onViewDetachedFromWindow(holder)
        } else {
            mAdapter?.apply {
                this.onViewAttachedToWindow(holder)
            }
        }
    }

    override fun onFailedToRecycleView(holder: RecyclerView.ViewHolder): Boolean {
        return if (holder is ViewHolder) {
            super.onFailedToRecycleView(holder)
        } else {
            mAdapter!!.onFailedToRecycleView(holder)
        }
    }

    override fun onAttachedToRecyclerView(recyclerView: RecyclerView) {
        mAdapter?.onAttachedToRecyclerView(recyclerView)
    }

    override fun onDetachedFromRecyclerView(recyclerView: RecyclerView) {
        mAdapter?.onDetachedFromRecyclerView(recyclerView)
    }

    override fun onViewRecycled(holder: RecyclerView.ViewHolder) {
        if (holder is ViewHolder) {
            super.onViewRecycled(holder)
        } else {
            mAdapter?.onViewRecycled(holder)
        }
    }

    /**设置被包装的adapter。同一个adapter对象不能设置多次*/
    fun setAdapter(adapter: RecyclerView.Adapter<RecyclerView.ViewHolder>) {
        require(adapter !is HeaderViewAdapter) {
            //被包装的adapter不能是HeaderViewAdapter。
            "Cannot wrap a HeaderViewAdapter"
        }
        mAdapter = adapter
        //注册mAdapter的数据变化监听
        mAdapter?.registerAdapterDataObserver(mObserver)
        notifyDataSetChanged()
    }

    /**获取被包装的adapter*/
    fun getAdapter(): RecyclerView.Adapter<RecyclerView.ViewHolder>? {
        return mAdapter
    }

    /**判断当前位置是不是头部*/
    /**这里的position是整个列表(包含HeaderView和FooterView)的position*/
    fun isHeader(position: Int): Boolean {
        return position < getHeadersCount()
    }

    /**判断当前位置是不是底部*/
    /**这里的position是整个列表(包含HeaderView和FooterView)的position*/
    fun isFooter(position: Int): Boolean {
        return itemCount - position <= getFootersCount()
    }

    /**获取HeaderView的个数*/
    fun getHeadersCount(): Int {
        return mHeaderViewInfos.size
    }

    /**获取FooterView的个数*/
    fun getFootersCount(): Int {
        return mFooterViewInfos.size
    }

    /**添加HeaderView*/
    fun addHeaderView(view: View) {
        addHeaderView(view, generateUniqueViewType())
    }

    private fun addHeaderView(view: View, viewType: Int) {
        val info: FixedViewInfo = FixedViewInfo()
        info.view = view
        info.itemViewType = viewType
        mHeaderViewInfos.add(info)
        notifyDataSetChanged()
    }

    /**删除HeaderView*/
    fun removeHeaderView(view: View): Boolean {
        mHeaderViewInfos.forEach {
            if (it.view == view) {
                mHeaderViewInfos.remove(it)
                notifyDataSetChanged()
                return true
            }
        }
        return false
    }

    /**添加FooterView*/
    fun addFooterView(view: View) {
        addFooterView(view, generateUniqueViewType())
    }

    fun addFooterView(view: View, viewType: Int) {
        val info: FixedViewInfo = FixedViewInfo()
        info.view = view
        info.itemViewType = viewType
        mFooterViewInfos.add(info)
        notifyDataSetChanged()
    }

    /**删除FooterView*/
    fun removeFooterView(view: View): Boolean {
        mFooterViewInfos.forEach {
            if (it.view == view) {
                mFooterViewInfos.remove(it)
                notifyDataSetChanged()
                return true
            }
        }
        return false
    }

    /**生成一个唯一的数，用于标识HeaderView或FooterView的type类型，并且保证类型不会重复*/
    private fun generateUniqueViewType(): Int {
        val count: Int = itemCount
        while (true) {
            //生成一个随机数
            var viewType: Int = (Math.random() * Int.MAX_VALUE + 1).toInt()
            //判断viewType是否被使用
            var isExist: Boolean = false
            for (i in 0 until count) {
                if (viewType == getItemViewType(i)) {
                    isExist = true
                    break
                }
            }
            //判断该viewType还没被使用，则返回。否则进行下一次循环，重新生成随机数
            if (!isExist) {
                return viewType
            }
        }
    }

    /*** 根据viewType查找对应的HeaderView 或 FooterView。没有找到则返回null。*/
    private fun findViewForInfo(viewType: Int): View? {
        /**遍历Header*/
        for (index in mHeaderViewInfos.indices) {
            if (mHeaderViewInfos[index].itemViewType == viewType) {
                return mHeaderViewInfos[index].view
            }
        }

        /**遍历Footer*/
        for (index in mFooterViewInfos.indices) {
            if (mFooterViewInfos[index].itemViewType == viewType) {
                return mFooterViewInfos[index].view
            }
        }
        /**如果都没有  返回null*/
        return null
    }

    inner class FixedViewInfo {
        /**保存HeaderView或FooterView*/
        var view: View? = null

        /**保存HeaderView或FooterView对应的viewType*/
        var itemViewType: Int = 0
    }

    companion object {
        class ViewHolder : RecyclerView.ViewHolder {
            constructor(itemView: View) : super(itemView)
        }
    }

    private fun isStaggeredGridLayout(holder: RecyclerView.ViewHolder): Boolean {
        val layoutParams: ViewGroup.LayoutParams = holder.itemView.layoutParams
        return layoutParams != null && layoutParams is StaggeredGridLayoutManager.LayoutParams
    }

    private fun handleLayoutIfStaggeredGridLayout(holder: RecyclerView.ViewHolder, position: Int) {
        if (isHeader(position) || isFooter(position)) {
            val p: StaggeredGridLayoutManager.LayoutParams =
                holder.itemView.layoutParams as StaggeredGridLayoutManager.LayoutParams
        }
    }
}